package xin.clips.common.core.controller;

import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import xin.clips.common.core.domain.AjaxResult;
import xin.clips.common.core.domain.AjaxResult.Type;
import xin.clips.common.core.domain.entity.SysUser;
import xin.clips.common.core.page.PageDomain;
import xin.clips.common.core.page.TableDataInfo;
import xin.clips.common.core.page.TableSupport;
import xin.clips.common.utils.DateUtils;
import xin.clips.common.utils.PageUtils;
import xin.clips.common.utils.ServletUtils;
import xin.clips.common.utils.ShiroUtils;
import xin.clips.common.utils.StringUtils;
import xin.clips.common.utils.sql.SqlUtil;

/**
 * web层通用数据处理
 *
 * @author ruoyi
 */
public class BaseController {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 将前台传递过来的日期格式的字符串，自动转化为Date类型
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // Date 类型转换
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(DateUtils.parseDate(text));
            }
        });
    }

    /**
     * 设置请求分页数据
     */
    protected void startPage() {
        PageUtils.startPage();
    }

    /**
     * 设置请求排序数据
     */
    protected void startOrderBy() {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            PageHelper.orderBy(orderBy);
        }
    }

    /**
     * 清理分页的线程变量
     */
    protected void clearPage() {
        PageUtils.clearPage();
    }

    /**
     * 获取request
     */
    public HttpServletRequest getRequest() {
        return ServletUtils.getRequest();
    }

    /**
     * 获取response
     */
    public HttpServletResponse getResponse() {
        return ServletUtils.getResponse();
    }

    /**
     * 获取session
     */
    public HttpSession getSession() {
        return getRequest().getSession();
    }

    /**
     * 响应请求分页数据
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    protected TableDataInfo getDataTable(List<?> list) {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(0);
        rspData.setRows(list);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }

    /**
     * 响应返回结果
     *
     * @param rows 影响行数
     * @return 操作结果
     */
    protected AjaxResult toAjax(int rows) {
        return rows > 0 ? success() : error();
    }

    /**
     * 响应返回结果
     *
     * @param result 结果
     * @return 操作结果
     */
    protected AjaxResult toAjax(boolean result) {
        return result ? success() : error();
    }

    /**
     * 返回成功
     */
    public AjaxResult success() {
        return AjaxResult.success();
    }

    /**
     * 返回失败消息
     */
    public AjaxResult error() {
        return AjaxResult.error();
    }

    /**
     * 返回成功消息
     */
    public AjaxResult success(String message) {
        return AjaxResult.success(message);
    }

    /**
     * 返回成功数据
     */
    public static AjaxResult success(Object data) {
        return AjaxResult.success("操作成功", data);
    }

    /**
     * 返回失败消息
     */
    public AjaxResult error(String message) {
        return AjaxResult.error(message);
    }

    /**
     * 返回错误码消息
     */
    public AjaxResult error(Type type, String message) {
        return new AjaxResult(type, message);
    }

    /**
     * 页面跳转
     */
    public String redirect(String url) {
        return StringUtils.format("redirect:{}", url);
    }

    /**
     * 获取用户缓存信息
     */
    public SysUser getSysUser() {
        return ShiroUtils.getSysUser();
    }

    /**
     * 设置用户缓存信息
     */
    public void setSysUser(SysUser user) {
        ShiroUtils.setSysUser(user);
    }

    /**
     * 获取登录用户id
     */
    public Long getUserId() {
        return getSysUser().getUserId();
    }

    /**
     * 获取登录用户名
     */
    public String getLoginName() {
        return getSysUser().getLoginName();
    }


    public static String getPageHtml(int pageNumber, int pageSize, int totalCount, String callback) {
        return getPageHtml(pageNumber, pageSize, totalCount, 6, callback);
    }

    public static String getPageHtml(int pageNumber, int pageSize, int totalCount, int showPages, String callback) {
        assert pageNumber > 0;
        assert pageSize > 1;
        assert showPages >= 3;

        StringBuffer sb = new StringBuffer();
        int totalPage = (totalCount + pageSize - 1) / pageSize;

        if (totalCount > 0) {
            sb.append("<div class=\"page_list\">");
            // 上一页，当前页为首页时禁用状态
            if (pageNumber == 1) {
                sb.append("<a href=\"javascript:;\" class=\"top_page disabled\">首页</a>");
                sb.append("<a href=\"javascript:;\" class=\"page_prev disabled\">上一页</a>");
            } else {
                sb.append("<a href=\"javascript:" + callback + "(1)\" class=\"top_page\">首页</a>");
                sb.append("<a href=\"javascript:" + callback + "(" + (pageNumber - 1) + ")\" class=\"page_prev\">上一页</a>");
            }
            LinkedList<Integer> list = new LinkedList<>();
            if (totalPage <= showPages) {
                for (int i = 1; i <= totalPage; i++) {
                    list.add(i);
                }
            } else {
                list.add(pageNumber);
                while (list.size() < showPages) {
                    // 以最前方页码继续向前推页码
                    Integer first = list.peekFirst();
                    // 确保插入的新页码不会小于1
                    if (first > 1) {
                        list.addFirst(first - 1);
                    }
                    // 确保不过超过需要显示的页码
                    if (list.size() >= showPages) {
                        break;
                    }
                    // 以当最后页码向后推页码
                    Integer last = list.peekLast();
                    // 确保新增页码不会超过最大页码
                    if (last < totalPage) {
                        list.addLast(last + 1);
                    }
                }
                if (list.peekFirst() != 1) {
                    list.addFirst(0);// 0代表...
                }
                if (list.peekLast() != totalPage) {
                    list.addLast(0);// 0代表...
                }
            }

            for (int i = 0; i < list.size(); i++) {
                Integer page = list.get(i);
                if (i == 0 && page == 0) {
                    sb.append("<a href='javascript:" + callback + "(" + Math.max(page, 1) + ");' class='shrink'>...</a>");
                } else if (i == list.size() - 1 && page == 0) {
                    sb.append("<a href='javascript:" + callback + "(" + Math.min(page, totalPage) + ");' class='shrink'>...</a>");
                } else if (pageNumber == page) {
                    sb.append("<a href='javascript:" + callback + "(" + page + ");' class='current'>" + page + "</a>");
                } else {
                    sb.append("<a href='javascript:" + callback + "(" + page + ");'>" + page + "</a>");
                }
            }
            if (pageNumber == totalPage) {
                sb.append("<a href='javascript:;' class='page_next disabled'>下一页</a>");
                sb.append("<a href='javascript:;' class='end_page disabled'>尾页</a>");
            }
            if (pageNumber != totalPage) {
                sb.append("<a href='javascript:" + callback + "(" + (pageNumber + 1) + ")' class='page_next'>下一页</a>");
                sb.append("<a href='javascript:" + callback + "(" + totalPage + ")' class='end_page'>尾页</a>");
            }
            sb.append("</div>");
        }

        return sb.toString();
    }
}
